package com.handpay.framework;

import android.content.Context;
import android.os.AsyncTask;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONException;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HurlStack;
import com.android.volley.toolbox.Volley;
import com.handpay.framework.download.DownloadRequest;
import com.handpay.framework.download.ProgressListener;
import com.handpay.framework.fastjson.FastJsonHelper;
import com.handpay.framework.utils.CustomRetryPolicy;
import com.handpay.framework.utils.MyAsyncTask;
import com.handpay.zztong.hp.R;
import com.handpay.zztong.hp.base.activity.BaseActivity;
import com.handpay.zztong.hp.bean.ResponseBean;
import com.handpay.zztong.hp.config.ZZTConfig;
import com.handpay.zztong.hp.log.HPLog;
import com.handpay.zztong.hp.utils.MacAddressUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;

import de.enough.polish.util.ZipUtil;
import se.krka.kahlua.vm.LuaTable;

import static com.handpay.framework.fastjson.FastJsonHelper.getObject;

public class HttpSFTConnector {
    private static final byte HttpTypeNONE = 0;
    // private static final byte HttpTypeREQUEST=1;
    private static final byte HttpTypeDataCOMPILED = 2;
    private static final byte HttpTypeDataUNCOMPILED = 3;
    private static final byte HttpTypeDataFILE = 4;
    private static byte datatype = HttpTypeNONE;
    // 0-send 1-recieve
    private static final String HEADER_NAME_IMEI = "X-HPIMEI"; // 0
    private static final String HEADER_NAME_MAC = "X-HPMAC"; // 0
    private static final String HEADER_NAME_SESSIONID = "X-HPSessionID"; // 0,1
    private static final String HEADER_NAME_Version = "X-HPVersion"; // 0
    private static final String HEADER_NAME_SIGNATURE = "X-HPSignature"; // 0,1
    private static final String HEADER_NAME_TerminalUserId = "X-HPTerminalUserID"; // 0,1
    private static final String HEADER_NAME_KEYEXCHANGE = "X-HPKeyExchange"; // 0,1
    private static final String HEADER_NAME_CONTENTTYPE = "X-HPContentType"; // 1
    private static final String HEADER_NAME_DATALENGTH = "X-HPDataLength"; // 1
    private static final String HEADER_NAME_COMPRESSED = "X-HPCompressed"; // 1
    private static final String HEADER_NAME_CACHE = "X-HPCache"; // 1
    private static final String HEADER_NAME_HPTUDID = "X-HPTUDID";
    // private boolean is_connect = false;
    // private static int cnt_connect = 0;
    // private static boolean connectChecked = false;
    public static final int DEFAULT_TIME_OUT = 10 * 1000; //默认网络请求超时时间
    private static final String CMWAPUrl = "10.0.0.172:80";
    private static String connectUrl = null;
    private static String onlineHostHeader = null;
    private static String keExchange = null;
    private static boolean isDoRSA = false;

    private static final byte CMNET_TYPE = 1;
    private static final byte CMWAP_TYPE = 2;
    private static byte NET_type = CMNET_TYPE;
    protected static byte currentConnectType = NET_type;
    private static boolean isDataCompress = false;
    // private static int datalen = -1;
    // private static byte saveType=HandPayPath.PATH_CACHE;
    // private static String signature = null;
    private static String sessionID;
    private static Request<?> byteRequest = null;
    private static RequestQueue mRequestQueue;
    private static HttpSFTConnector instance;
    private static Context mContext;

    private HttpSFTConnector(Context context) {
        this.mContext = context.getApplicationContext();
        if (ZZTConfig.isUseHTTPS) {
            //双向认证
            InputStream p12Keystore = context.getApplicationContext().getResources().openRawResource(R.raw.sandpayclient_hpd);
            InputStream trustKeyStore = context.getApplicationContext().getResources().openRawResource(R.raw.sandpayserver_hpd);
            mRequestQueue = Volley.newRequestQueue(mContext, new HurlStack(null, SSLCustomSocketFactory.getSocketFactory(p12Keystore, "1234567890", trustKeyStore)));
            //单项认证
//            InputStream trustKeyStore = getResources().openRawResource(R.raw.handpayssl);
//            requestQueue = Volley.newRequestQueue(getApplicationContext(), new HurlStack(null, SSLCustomSocketFactory.getSocketFactory(trustKeyStore, "handpay")));
        } else {
            mRequestQueue = Volley.newRequestQueue(mContext);
        }
    }

    public static synchronized HttpSFTConnector init(Context context) {
        if (instance == null) {
            synchronized (HttpSFTConnector.class) {
                if (instance == null) {
                    instance = new HttpSFTConnector(context);
                }
            }
        }
        return instance;
    }


    private static void calculateAction(String action) {
        String url = ClientEngine.APPSERVERURL + action;
        calculateUrl(url);
    }

    private static void calculateUrl(String url) {
        if (currentConnectType == CMWAP_TYPE) {
            String tmpUrl = "http://";
            if (!url.startsWith(tmpUrl)) {
                tmpUrl = "https://";
            }
            int si = tmpUrl.length();

            int ei = url.indexOf("/", si);
            if (ei < 0) {
                ei = url.length();
            }

            onlineHostHeader = url.substring(si, ei);
            connectUrl = tmpUrl + CMWAPUrl + url.substring(ei);
        } else {
            // cmnet
            onlineHostHeader = null;
            connectUrl = url;
        }
    }

    /**
     * 组织Http请求的Header
     *
     * @return
     */
    private static Hashtable<String, String> treateReqHeader() {
        Hashtable<String, String> headers = new Hashtable<String, String>();
        // http header里增加参数。
        String imei = ClientEngine.getInstance().getIMEI();
//        String mac = ClientEngine.getInstance().getMac();
        String mac = MacAddressUtils.getMacAddress(mContext);
        if (!TextUtils.isEmpty(imei)) {
            headers.put(HEADER_NAME_IMEI, imei);
        }
        if (!TextUtils.isEmpty(mac)) {
            headers.put(HEADER_NAME_MAC, mac);
        }
        String deviceUuid = ClientEngine.getInstance().getDeviceUuid();
        if (!TextUtils.isEmpty(deviceUuid)) {
            headers.put(HEADER_NAME_HPTUDID, deviceUuid);
        }
        if (onlineHostHeader != null) {
            headers.put("X-Online-Host", onlineHostHeader);
        }
        if (sessionID != null) {
            headers.put(HEADER_NAME_SESSIONID, sessionID);
        }
        headers.put(HEADER_NAME_Version, ClientEngine.HPVIRSION);
        headers.put("Content-Type", "application/x-www-form-urlencoded");//   headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");HttpUrlconnection 会报500
        headers.put("Connection", "Keep-Alive");
        headers.put("X-HPDataType", "json");
        // terminalUserId和密钥交换没有关系
        String terminalu = (String) ClientEngine.getInstance().getRMSData(HEADER_NAME_TerminalUserId);
        if (terminalu != null) {
            headers.put(HEADER_NAME_TerminalUserId, terminalu);
        }
        String seedstr = SecureManager.getInstance().Is_NeedCreateSeed();
//        HPLog.i(HPLog.YL_TAG, "seedstr:" + seedstr);
        if (seedstr != null) {
            // 做密钥交换，默认交换是失败了
            isDoRSA = true;
            keExchange = null;
            byte[] data = null;
            try {
                data = seedstr.getBytes("UTF-8");
            } catch (Exception e) {
                data = seedstr.getBytes();
            }
            String rsts = SecureManager.getInstance().rsaEnCrypt(data);
            rsts = "testrsaid|" + rsts;
            HPLog.i(HPLog.YL_TAG, "rsts:" + rsts);
            headers.put(HEADER_NAME_KEYEXCHANGE, rsts);
        } else {
            isDoRSA = false;
        }
        return headers;
    }

    /**
     * 解析Http响应的Header
     *
     * @param headers
     * @return
     */
    private static Hashtable<String, String> treateRspHeader(Map<String, String> headers) {
        Hashtable<String, String> headertable = new Hashtable<String, String>();
        if (headers != null) {
            datatype = HttpSFTConnector.HttpTypeDataUNCOMPILED;
            for (String key : headers.keySet()) {
                String name = key;
                String value = headers.get(key);
                if (name.compareTo(HEADER_NAME_SESSIONID) == 0) {
                    sessionID = value;
                }
                if (name.compareTo(HEADER_NAME_COMPRESSED) == 0) {
                    isDataCompress = value.compareTo("true") == 0;
                } else if (name.compareTo(HEADER_NAME_CONTENTTYPE) == 0) {
                    if (value.compareTo("data/binary") == 0) {
                        datatype = HttpSFTConnector.HttpTypeDataCOMPILED;
                    } else if (value.compareTo("file") == 0) {
                        datatype = HttpSFTConnector.HttpTypeDataFILE;
                    } else {
                        datatype = HttpSFTConnector.HttpTypeDataUNCOMPILED;
                    }
                } else if (name.compareTo(HEADER_NAME_DATALENGTH) == 0) {
                    // datalen = Integer.parseInt(value);
                } else if (name.compareTo(HEADER_NAME_CACHE) == 0) {
                    if (value.compareTo("persistent") == 0) {
                        // saveType = HandPayPath.PATH_FILE;
                    } else {
                        // saveType = HandPayPath.PATH_CACHE;
                    }
                } else if (name.compareTo(HEADER_NAME_TerminalUserId) == 0) {
                    ClientEngine.getInstance().saveRMSData(HEADER_NAME_TerminalUserId, value);
                } else if (name.compareTo(HEADER_NAME_SIGNATURE) == 0) {
                    // signature = value;
                } else if (name.compareTo(HEADER_NAME_KEYEXCHANGE) == 0) {
                    keExchange = value;
                }
                headertable.put(name, value);
            }
        }
        if (isDoRSA) {
            SecureManager.getInstance().ReSetSecure(keExchange);
        }
        return headertable;
    }


    /**
     * HttpEngine.Key_RespCode:int HttpEngine.Key_RespHeaders:Hashtable<String,
     * String> HttpEngine.Key_RespData:byte[]
     */
    private static synchronized Hashtable<String, Object> connectDo(Context context, String action, Hashtable<String, String> params) {
        calculateAction(action);
        return connectDoUrl(context, params);
    }

    /*
     * 通过URL发送hashtable数据，为新的架构而加
     */
    public static synchronized Hashtable<String, Object> doPost(Context context, String url, Hashtable<String, String> data) {
        Hashtable<String, Object> respData = null;

        connectUrl = url;
        respData = connectDoUrl(context, data);
        respData.put("dataCompressFlag", datatype == HttpTypeDataCOMPILED);
        return respData;
    }

    /**
     * @param context   上下文
     * @param action    请求action
     * @param params    请求参数
     * @param byteArray 图片字节数组
     * @param cls       需要解析的bean的字节码
     * @return 返回请求服务器结果Bean
     */
    public static ResponseBean uploadPic2ServerWithJson(Context context, final Class<? extends ResponseBean> cls, String action, Hashtable<String, String> params, byte[] byteArray) {
        calculateAction(action);
        return getObject(HttpEngine.uploadByteJson(context, connectUrl, treateReqHeader(), params, DEFAULT_TIME_OUT, byteArray), cls);
    }

    public static Hashtable<String, Object> uploadPic2Server(Context context, String action, Hashtable<String, String> params, byte[] byteArray) {
        HPLog.i("uploadPic2Server", "connectDo");
        calculateAction(action);
        Hashtable<String, String> reqHeaders = treateReqHeader();
        Hashtable<String, Object> resp = HttpEngine.uploadByte(context, connectUrl, reqHeaders, params, DEFAULT_TIME_OUT, byteArray);
        Hashtable<String, String> respHeaders = treateRspHeader((Map<String, String>) resp.get(HttpEngine.Key_RespHeaders));
        resp.put(HttpEngine.Key_RespHeaders, respHeaders);
        byte cache[] = (byte[]) resp.get(HttpEngine.Key_RespData);
        if (isDataCompress) {
            try {
                cache = ZipUtil.decompress(cache);
                resp.put(HttpEngine.Key_RespData, cache);
            } catch (IOException e) {

            }
        }
        HPLog.i("postResp", "connectUrl: " + connectUrl);
        try {
            HPLog.i("post", "data: " + new String(cache, "UTF-8") + ":end");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }

    /**
     * 获取服务器数据
     *
     * @param cls     需要返回的对象的字节码
     * @param context 上下文
     * @param action  action
     * @param params  请求参数
     * @return 返回需要获取的对象
     */
    public static ResponseBean postData2ServerWithJson(Context context, final Class<? extends ResponseBean> cls, String action, Hashtable<String, String> params) {
        calculateAction(action);
        HPLog.d(HPLog.SSX_TAG, "url:" + connectUrl);
        HPLog.d(HPLog.SSX_TAG, "paramers:" + params.toString());
        return getObject(HttpEngine.postJson(context, connectUrl, treateReqHeader(), params, DEFAULT_TIME_OUT), cls);
    }

    /***
     * 使用原生HttpUrlconnection异步请求
     * @param context 上下文
     * @param action 请求Action
     * @param paramers 请求参数
     */
    public static void asyncPostWithHttpUrlConnection(final Context context, final String action, final Hashtable<String, String> paramers, final Class<? extends ResponseBean> cls, final NetEngineListener listener, final boolean showAlert) {
        calculateAction(action);
        HPLog.i(HPLog.SSX_TAG, "-----------------------------request start------------------------");
        HPLog.i(HPLog.SSX_TAG, "url:" + connectUrl);
        HPLog.i(HPLog.SSX_TAG, paramers.toString());
        HPLog.i(HPLog.SSX_TAG, treateReqHeader().toString());
        HPLog.i(HPLog.SSX_TAG, "-----------------------------request end------------------------");
        new AsyncTask<String, Void, String>() {
            @Override
            protected void onPostExecute(String result) {
                HPLog.i(HPLog.SSX_TAG, "-----------------------------reponse start------------------------");
                HPLog.json(HPLog.SSX_TAG, result);
                HPLog.i(HPLog.SSX_TAG, "-----------------------------response end------------------------");
                if (!TextUtils.isEmpty(result)) {
                    ResponseBean responseBean = FastJsonHelper.getObject(result, cls);
                    listener.callbackJsonNetResponse(action, responseBean, showAlert);
                }
            }

            @Override
            protected String doInBackground(String... params) {
                return HttpEngine.postJson(context, params[0], treateReqHeader(), paramers, DEFAULT_TIME_OUT);
            }
        }.execute(connectUrl);
    }

    /**
     * 发送数据到后台。
     *
     * @param action
     * @param params
     * @return true表示发送成功，false表示发送失败。 @ modify cyg 为了方便UI做提示，直接把结果返回
     */
    public static Hashtable<String, Object> postData2Server(Context context, String action, Hashtable<String, String> params) {
        return connectDo(context, action, params);
    }

    /**
     * 用于非瀚银url的访问。
     *
     * @param url
     * @param params
     * @return
     */
    private static synchronized Hashtable<String, Object> connectDoUrl(Context context, String url, String params) {
        calculateUrl(url);
        return connectDoUrl(context, params);
    }

    /**
     * 用于非瀚银url的访问。
     *
     * @param params
     * @return
     */

    private static Hashtable<String, Object> connectDoUrl(Context context, String params) {
        Hashtable<String, String> reqHeaders = treateReqHeader();
        HPLog.i(HPLog.YL_TAG, "reqHeader:" + reqHeaders.toString());
        Hashtable<String, Object> resp = HttpEngine.post(context, connectUrl, reqHeaders, params, DEFAULT_TIME_OUT);
        Hashtable<String, String> respHeaders = treateRspHeader((Map<String, String>) resp.get(HttpEngine.Key_RespHeaders));
        resp.put(HttpEngine.Key_RespHeaders, respHeaders);
        byte cache[] = (byte[]) resp.get(HttpEngine.Key_RespData);
        if (isDataCompress) {
            try {
                cache = ZipUtil.decompress(cache);
                resp.put(HttpEngine.Key_RespData, cache);
            } catch (IOException e) {

            }
        }
        HPLog.i("postResp", "connectUrl: " + connectUrl);
        try {
            HPLog.i("post", " " + new String(cache, "UTF-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }

    /***
     * @param params
     * @return
     */
    private static Hashtable<String, Object> connectDoUrl(Context context, Hashtable<String, String> params) {
        Hashtable<String, String> reqHeaders = treateReqHeader();
        HPLog.i(HPLog.YL_TAG, "reqHeader:" + reqHeaders.toString());
        Hashtable<String, Object> resp = HttpEngine.post(context, connectUrl, reqHeaders, params, DEFAULT_TIME_OUT);
        Map<String, String> headers = (Map<String, String>) resp.get(HttpEngine.Key_RespHeaders);
        Hashtable<String, String> respHeaders = treateRspHeader(headers);
        HPLog.i(HPLog.YL_TAG, "respHeader:" + respHeaders.toString());
        if (isDoRSA && null == keExchange) {
            int responseCode = (Integer) resp.get(HttpEngine.Key_RespCode);
            if (responseCode == 200 || responseCode == 206) {
                // 后台响应成功，但是交换密钥没有成功. 标示网络错误。
                HPLog.e("connectDoUrl", "exchange key failed");
                resp.put(HttpEngine.Key_RespCode, -2);
                if (TextUtils.isEmpty((String) resp.get(HttpEngine.Key_RespErrMsg))) {
                    resp.put(HttpEngine.Key_RespErrMsg, ClientEngine.getInstance().getString(R.string.dataerror));
                }
            }
        }
        resp.put(HttpEngine.Key_RespHeaders, respHeaders);
        byte cache[] = (byte[]) resp.get(HttpEngine.Key_RespData);
        if (isDataCompress) {
            try {
                cache = ZipUtil.decompress(cache);
                resp.put(HttpEngine.Key_RespData, cache);
            } catch (IOException e) {

            }
        }
        try {
            HPLog.i("post", "data: " + new String(cache, "UTF-8") + ":end");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }

    /***
     * 错误信息处理
     *
     * @param resp
     * @param isDataCompiled
     */
    private static void dealWithExchangeKeyTimeout(Hashtable<String, Object> resp, boolean isDataCompiled) {
        // 预处理数据
        if (null == resp) {
            return;
        }
        byte data[] = (byte[]) resp.get(HttpEngine.Key_RespData);
        if (null == data) {
            return;
        }
        LuaTable luaTable = LuaTableUtil.stringToLuaTable(data, isDataCompiled);
        if (null == luaTable) {
            return;
        }
        Object respCode = luaTable.rawget("responseCode");
        if (null == respCode) {
            return;
        }
        //
        String strRespCode = null;
        if (respCode instanceof Double) {
            strRespCode = String.valueOf(respCode);
        } else if (respCode instanceof String) {
            strRespCode = (String) respCode;
        }
        if (TextUtils.isEmpty(strRespCode)) {
            return;
        }
        // 具体符号，参见文档.如果密钥过期，重新生成密钥。-----本应该告知密钥需要重新生成。
        if ("S131".equals(strRespCode)) {
            SecureManager.getInstance().ReSetSecure(null);
        }
    }

    public static void doVolleyJsonPost(final NetEngineListener listener, final String action, final Class<? extends ResponseBean> cls, final Hashtable<String, String> params, final boolean showAlert, int timeout) {
        calculateAction(action);
        final Hashtable<String, String> reqHeaders = treateReqHeader();
        final Hashtable<String, Object> resp = new Hashtable<String, Object>();
        HPLog.i(HPLog.YL_TAG, "-----------------------------request start------------------------");
        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
        HPLog.i(HPLog.YL_TAG, "requestHeaders:" + reqHeaders.toString());
        HPLog.i(HPLog.YL_TAG, "requestBody:" + params.toString());
        HPLog.i(HPLog.YL_TAG, "-----------------------------request end------------------------");
        byteRequest = new ByteRequest(Request.Method.POST, connectUrl, new Response.Listener<byte[]>() {
            ResponseBean rspBean;

            @Override
            public void onResponse(byte[] response) {
                try {
                    String result = new String(response, "UTF-8");
                    if (TextUtils.isEmpty(result)) {
                        HPLog.e(HPLog.SSX_TAG, "server return data is null");
                        rspBean = new ResponseBean();
                        rspBean.setErrMessage("服务器返回数据为空!");
                        rspBean.setResponseCode("-1");
                        listener.callbackJsonNetResponse(action, rspBean, showAlert);
                        return;
                    }
                    try {
                        rspBean = getObject(result, cls);
                    } catch (JSONException e) {
                        rspBean = new ResponseBean();
                        rspBean.setErrMessage("服务器数据解析异常!");
                        rspBean.setResponseCode("-1");
                    }
                    String after;
                    if (result.contains("\r\n")) {
                        after = result.replace("\r\n", "");
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response start------------------------");
                        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
                        HPLog.i(HPLog.YL_TAG, "responseHeaders:" + resp.get(HttpEngine.Key_RespHeaders));
                        HPLog.json(HPLog.YL_TAG, after);
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response end------------------------");
                    } else {
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response start------------------------");
                        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
                        HPLog.i(HPLog.YL_TAG, "responseHeaders:" + resp.get(HttpEngine.Key_RespHeaders));
                        HPLog.json(HPLog.YL_TAG, result);
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response end------------------------");
                    }
                } catch (UnsupportedEncodingException e) {
                    rspBean = new ResponseBean();
                    rspBean.setErrMessage("服务器数据编码异常!");
                    rspBean.setResponseCode("-1");
                }
                Map<String, String> headers = (Map<String, String>) resp.get(HttpEngine.Key_RespHeaders);
                Hashtable<String, String> respHeaders = treateRspHeader(headers);
                resp.put(HttpEngine.Key_RespHeaders, respHeaders);
                resp.put(HttpEngine.Key_RespCode, 200);
                resp.put(HttpEngine.Key_RespData, response);
                HPLog.i(HPLog.YL_TAG, rspBean.toString());
                listener.callbackJsonNetResponse(action, rspBean, showAlert);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                ResponseBean responseBean = new ResponseBean();
                responseBean.setResponseCode("-1");
                Class volleyErrorClass = volleyError.getClass();
                String errorMsg = null;
                try {
                    if (volleyError.networkResponse.statusCode > 0) {
                        responseBean.setResponseCode(volleyError.networkResponse.statusCode + "");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    responseBean.setResponseCode("-1");
                }
                if (volleyErrorClass == ServerError.class) {
                    errorMsg = "服务不可用";
                } else if (volleyErrorClass == AuthFailureError.class) {
                    errorMsg = "身份验证未通过";
                } else if (volleyErrorClass == ParseError.class) {
                    errorMsg = "解析数据错误";
                } else if (volleyErrorClass == TimeoutError.class) {
                    errorMsg = "网络连接超时";
                } else if (volleyError instanceof NetworkError) {
                    if (volleyErrorClass == NoConnectionError.class) {
                        errorMsg = "无法连接服务器";
                    }
                } else {
                    errorMsg = "网络连接异常";
                }
                responseBean.setErrMessage(errorMsg);
                listener.callbackJsonNetResponse(action, responseBean, showAlert);
            }
        }) {
            @Override
            protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
                resp.put(HttpEngine.Key_RespHeaders, response.headers);
                return super.parseNetworkResponse(response);
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> map = new HashMap<>();
                for (Entry<String, String> entry : reqHeaders.entrySet()) {
                    String name = entry.getKey();
                    String value = entry.getValue();
                    map.put(name, value);
                }
                return map;
            }

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                // 在这里设置需要post的参数
                Map<String, String> map = new HashMap<>();
                for (Entry<String, String> entry : params.entrySet()) {
                    String name = entry.getKey();
                    String value = entry.getValue();
                    map.put(name, value);
                }
                return map;
            }
        };
        if (timeout > 0) {
            byteRequest.setRetryPolicy(new CustomRetryPolicy(timeout));
        } else {
            byteRequest.setRetryPolicy(new CustomRetryPolicy(DEFAULT_TIME_OUT));
        }
        byteRequest.setTag(action);
        if (mRequestQueue != null) {
            mRequestQueue.add(byteRequest);
        } else {
            throw new IllegalArgumentException("RequestQueue is not initialized,please check your appaction!");
        }
    }

    /***
     * 网络请求
     *
     * @param listener     回调监听
     * @param action       请求action
     * @param params       请求参数
     * @param showAlert    是否弹出对话框
     * @param timeout      请求超时时间
     */
    public static void doVolleyPost(final NetEngineListener listener, final String action, final Hashtable<String, String> params, final boolean showAlert, int timeout) {
        calculateAction(action);
        final Hashtable<String, String> reqHeaders = treateReqHeader();
        final Hashtable<String, Object> resp = new Hashtable<String, Object>();
        HPLog.i(HPLog.YL_TAG, "-----------------------------request start------------------------new");
        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
        HPLog.i(HPLog.YL_TAG, "requestHeaders:" + reqHeaders.toString());
        HPLog.i(HPLog.YL_TAG, "requestBody:" + params!=null?params.toString():"params is null!");
        HPLog.i(HPLog.YL_TAG, "-----------------------------request end------------------------- new");
        byteRequest = new ByteRequest(Request.Method.POST, connectUrl, new Response.Listener<byte[]>() {
            @Override
            public void onResponse(byte[] response) {
                try {
                    String result = new String(response, "UTF-8");
                    String after;
                    if (result.contains("\r\n")) {
                        after = result.replace("\r\n", "");
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response start----------------------new");
                        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
                        HPLog.i(HPLog.YL_TAG, "responseHeaders:" + resp.get(HttpEngine.Key_RespHeaders));
                        HPLog.json(HPLog.YL_TAG, after);
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response end------------------------new");
                    } else {
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response start----------------------new");
                        HPLog.i(HPLog.YL_TAG, "url:" + connectUrl);
                        HPLog.i(HPLog.YL_TAG, "responseHeaders:" + resp.get(HttpEngine.Key_RespHeaders));
                        HPLog.json(HPLog.YL_TAG, result);
                        HPLog.i(HPLog.YL_TAG, "-----------------------------response end------------------------new");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Map<String, String> headers = (Map<String, String>) resp.get(HttpEngine.Key_RespHeaders);
                Hashtable<String, String> respHeaders = treateRspHeader(headers);
                resp.put(HttpEngine.Key_RespHeaders, respHeaders);
                resp.put(HttpEngine.Key_RespCode, 200);
                resp.put(HttpEngine.Key_RespData, response);
                listener.callbackNetResponse(action, resp, showAlert);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                commGetErrorMsg(volleyError, resp);
                listener.callbackNetResponse(action, resp, showAlert);
            }
        }) {
            @Override
            protected Response<byte[]> parseNetworkResponse(NetworkResponse response) {
                resp.put(HttpEngine.Key_RespHeaders, response.headers);
                return super.parseNetworkResponse(response);
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> map = new HashMap<>();
                for (Entry<String, String> entry : reqHeaders.entrySet()) {
                    String name = entry.getKey();
                    String value = entry.getValue();
                    map.put(name, value);
                }
                return map;
            }

            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                // 在这里设置需要post的参数
                Map<String, String> map = new HashMap<>();
                if(params!=null){
                    for (Entry<String, String> entry : params.entrySet()) {
                        String name = entry.getKey();
                        String value = entry.getValue();
                        map.put(name, value);
                    }
                }
                return map;
            }
        };
        if (timeout > 0) {
            byteRequest.setRetryPolicy(new CustomRetryPolicy(timeout));
        } else {
            byteRequest.setRetryPolicy(new CustomRetryPolicy(DEFAULT_TIME_OUT));
        }
        byteRequest.setTag(action);
        if (mRequestQueue != null) {
            mRequestQueue.add(byteRequest);
        } else {
            throw new IllegalArgumentException("RequestQueue is not initialized,please check your appaction!");
        }
    }

    /***
     * 统一处理Volley错误信息
     *
     * @param volleyError 错误信息
     * @param resp        返回数据集合
     */
    private static String commGetErrorMsg(VolleyError volleyError, Hashtable<String, Object> resp) {
        Class volleyErrorClass = volleyError.getClass();
        String message = null;
        String statusCodeStr = "";
        int statusCode = -1;
        try {
            statusCode = volleyError.networkResponse.statusCode;
            statusCodeStr = "";
            if (volleyError.networkResponse.statusCode > 0) {
                statusCodeStr = "[" + volleyError.networkResponse.statusCode + "]";
            }
//                    + volleyError.getMessage();
        } catch (Exception e) {
            e.printStackTrace();
        }
        HPLog.d(HPLog.SSX_TAG, "statusCode:" + statusCode);
        if (volleyErrorClass == ServerError.class) {
            message = "服务不可用" + statusCodeStr;
            resp.put(HttpEngine.Key_RespCode, statusCode);
            resp.put(HttpEngine.Key_RespErrMsg, message);
        } else if (volleyErrorClass == AuthFailureError.class) {
            message = "身份验证未通过" + statusCodeStr;
            resp.put(HttpEngine.Key_RespCode, statusCode);
            resp.put(HttpEngine.Key_RespErrMsg, message);
        } else if (volleyErrorClass == ParseError.class) {
            message = "解析数据错误" + statusCodeStr;
            resp.put(HttpEngine.Key_RespCode, statusCode);
            resp.put(HttpEngine.Key_RespErrMsg, message);
        } else if (volleyErrorClass == TimeoutError.class) {
            message = "网络连接超时" + statusCodeStr;
            resp.put(HttpEngine.Key_RespCode, statusCode);
            resp.put(HttpEngine.Key_RespErrMsg, message);
        } else if (volleyError instanceof NetworkError) {
            if (volleyErrorClass == NoConnectionError.class) {
                message = "无法连接服务器" + statusCodeStr;
                resp.put(HttpEngine.Key_RespCode, statusCode);
                resp.put(HttpEngine.Key_RespErrMsg, message);
            } else {
                message = "网络连接异常" + statusCodeStr;
                resp.put(HttpEngine.Key_RespCode, statusCode);
                resp.put(HttpEngine.Key_RespErrMsg, message);
            }
        } else {
            message = "重定向错误" + statusCodeStr;
            resp.put(HttpEngine.Key_RespCode, statusCode);
            resp.put(HttpEngine.Key_RespErrMsg, message);
        }
        return message;
    }


    /**
     * 指定url，访问，一般用于访问非瀚银url。先主要用于访问银联环境，以及测试用。
     *
     * @param activity
     * @param url
     * @param params
     * @param showAlert
     */
    public static void doPostUrl(final BaseActivity activity, final String url, final String params, final boolean showAlert) {
        new MyAsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... param) {
                Hashtable<String, Object> resp = connectDoUrl(activity, url, params);
//                activity.callbackNetResponse(url, resp, showAlert);
                return null;
            }

            @Override
            protected void onPostExecute(Void result) {

            }

            @Override
            protected void onPreExecute() {

            }
        }.execute();
    }

    /**
     * 使用Volley 下载文件
     *
     * @param downUrl  下载地址
     * @param filePath 文件路径
     */
    public static void downLoadFile(String downUrl, String filePath) {
        InputStream keyStore = mContext.getResources().openRawResource(R.raw.handpaydownlad);
        mRequestQueue = Volley.newRequestQueue(mContext, new HurlStack(null, SSLCustomSocketFactory.getSocketFactory(keyStore, "handpay")));
        DownloadRequest downloadRequest = new DownloadRequest(downUrl, filePath, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                HPLog.d(HPLog.SSX_TAG, response + "");
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                HPLog.d(HPLog.SSX_TAG, "onErrorResponse");
                String result = commGetErrorMsg(error, new Hashtable<String, Object>());
                HPLog.d(HPLog.SSX_TAG, "result" + result);
            }
        });
        downloadRequest.setRetryPolicy(new CustomRetryPolicy(DEFAULT_TIME_OUT));
        downloadRequest.setTag(downUrl);
        if (mRequestQueue != null) {
            mRequestQueue.add(downloadRequest);
        } else {
            throw new IllegalArgumentException("RequestQueue is not initialized,please check your appaction!");
        }
    }

    /**
     * 判断客户端，是不是已经有sessionId。一般来说，有就默认登录成功了。 一般用于登录后，和注册完成后。
     *
     * @return true，表示有，false，表示没有
     */
    public static boolean hasSessionID() {
        return !TextUtils.isEmpty(sessionID);
    }

}
